module;
#include <iterator>

export module Code_20_3_4;


template<typename FROM, typename TO>
struct IsConvertibleHelper
{
private:
    static void aux(TO);
    template<typename F,
        typename = decltype(aux(std::declval<F>()))>
    static std::true_type test(void*);
    template<typename>
    static std::false_type test(...);

public:
    using Type = decltype(test<FROM>(nullptr));
};

template<typename FROM, typename TO>
struct IsConvertibleT : IsConvertibleHelper<FROM, TO>::Type
{
};

template<typename FROM, typename TO>
using IsConvertible = typename IsConvertibleT<FROM, TO>::Type;

template<typename Iterator>
constexpr bool IsRandomAccessIterator = IsConvertible< typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>;

template<typename Iterator>
constexpr bool IsInputIterator = IsConvertible< typename std::iterator_traits<Iterator>::iterator_category, std::input_iterator_tag>;


template<typename T>
class Container 
{
public:
    //construct from an input iterator sequence:
    template<typename Iterator>
        requires IsInputIterator<Iterator>
    Container(Iterator first, Iterator last);

    // construct from a random access iterator sequence:
    template<typename Iterator>
        requires IsRandomAccessIterator<Iterator>
    Container(Iterator first, Iterator last);

    // convert to a container so long as the value types are convertible:
    template<typename U>
        requires IsConvertible<T, U>
    operator Container<U>() const;
};
export
namespace Code_20_3_4 {

    void run()
    {

    }
}
